上世纪中叶计算机问世后，很快，一种比汇编语言更抽象的语言在编程方面就异军突起了。早在1957年，Fortran作为第一种可用的高级程序设计语言问世。从那时起，成千上万种编程语言被开发出来。事实证明，所有的编译器都必须解决相同的任务，编译器的实现应该根据这些任务进行架构和设计。\par

抽象的来看，编译器由两部分组成:前端和后端。前端负责特定于语言的任务，读取源文件并计算语义分析表示，通常是带注释的抽象语法树(AST)。后端从前端的结果创建优化的机器码。区分前端和后端的动机是可重用性。假设前端和后端之间的接口定义得很好，就可以将一个C和一个Modula-2前端连接到同一个后端。或者，当有一个x86后端和一个Sparc后端，那么可以将您的C++前端与二者相连。\par

前端和后端有特定的结构。前端通常执行以下任务:\par

\begin{enumerate}
\item 词法分析器（Lexical analyzer，简称Lexer）读取源文件并生成一个令牌流。
\item 解析器从令牌流创建一个AST。
\item 语义分析器向AST添加语义信息。
\item 代码生成器从AST生成一个中间表示(IR)。
\end{enumerate}

中间表示是后端接口。后端执行以下任务:\par

\begin{enumerate}
\item 后端在IR上执行与目标无关的优化。
\item 然后为IR代码选择指令。
\item 之后，对指令执行与目标相关的优化。
\item 最后，产生汇编程序代码或目标文件。
\end{enumerate}

当然，这些指令只是概念上的，实现会有很大的不同。LLVM核心库将中间表示定义为后端标准接口，其他工具可以使用带注释的AST，并且C的预处理器是专用于C的。其可以实现为输出预处理C源的应用程序，也可以实现为词法分析器和解析器之间的中间件。某些情况下，AST不能显式构造。如果要实现的语言不是太复杂，可以组合解析器和语义分析器。然后在解析时生成代码，即使给定的编程语言实现没有显式地命名这些组件。不过，以上的任务是必须要完成的。\par

在下面的小节中，我们将为表达式语言构造一个编译器，该语言从其输入生成LLVM IR。LLVM静态编译器llc表示后端，可以使用它将IR编译成目标代码。这一切都要从定义一种语言开始。\par






















